//
// Created by l on 19-2-20.
//

#ifndef DAHUA_MYDAHUACAM_H
#define DAHUA_MYDAHUACAM_H
#include <arpa/inet.h>
#include <opencv2/opencv.hpp>
#include <signal.h>
#include <boost/thread.hpp>
#include "GenICam/System.h"
#include "GenICam/Camera.h"
#include "GenICam/StreamSource.h"
#include "GenICam/GigE/GigECamera.h"
#include "GenICam/GigE/GigEInterface.h"
#include "Infra/PrintLog.h"
#include "Memory/SharedPtr.h"
using namespace Dahua::GenICam;
using namespace Dahua::Infra;
namespace hitcrt{


    /**
* Copyright (C) 2019, HITCRT_VISION, all rights reserved.
* @brief 大华工业相机接口类
     * 用法构造函数里传入相机序列号，图像尺寸，曝光参数（默认尺寸1280*720，默认曝光1000.0，长度最大1280，高度最大1024）,调用grab函数抓图。
* @author 黎林
* -phone:18846140245;qq:1430244438
*/

    class MyDahuaCam {
    public:
        typedef std::shared_ptr<MyDahuaCam> Ptr;
        MyDahuaCam(std::string _SerialNumber="auto",int _width=1280,int height=1024,double exposure=1000.0,int brightness=100,int digitalshift=1,std::vector<double> _balance={1.0,1.0,1.0},int blacklevel=20,double gama=1,int gainraw=1,int sharpness=50);
        ~MyDahuaCam(){
            close();
        }

        bool grab();
        std::shared_ptr<cv::Mat> getImage(bool destroy=true); //抓单张图
            /**
         * @brief 设置连续/单张拍照时的触发模式和触发源。
         * @param bContious 
         * @return  
         * @author Milo
         */
        int32_t setGrabMode( bool bContious);  
        int32_t getGrabMode( bool &bContious);

        int32_t triggerSoftware(); //进行软件触发，适用于单次抓图
        int32_t setResolution( int nWidth, int nHeight); 
        int32_t getResolution( int64_t &nWidth, int64_t &nHeight);
        int32_t setBinning();
        int32_t getMaxResolution(int64_t &nWidthMax, int64_t &nHeightMax);
        int32_t setROI(int64_t nX, int64_t nY, int64_t nWidth, int64_t nHeight);
        int32_t getROI( int64_t &nX, int64_t &nY, int64_t &nWidth, int64_t &nHeight);
        int32_t getWidth( int64_t &nWidth);
        int32_t getHeight( int64_t &nHeight);
        int32_t setExposureTime( double dExposureTime);
        int32_t getExposureTime( double &dExposureTime);
        int32_t getExposureTimeMinMaxValue( double &dMinValue, double &dMaxValue);
        int32_t setGainRaw( double dGainRaw);  //设置增益
        int32_t getGainRaw( double &dGainRaw);
        //？？
        int32_t getGainRawMinMaxValue( double &dMinValue, double &dMaxValue);
        int32_t setGamma( double dGamma);
        int32_t getGamma(double &dGamma);
        int32_t getGammaMinMaxValue( double &dMinValue, double &dMaxValue);
        int32_t setBalanceRatio( double dRedBalanceRatio, double dGreenBalanceRatio, double dBlueBalanceRatio); //设置三者的白平衡
        int32_t setBalanceRatioR(double dRedBalanceRatio);
        int32_t setBalanceRatioG(double dGreenBalanceRatio);
        int32_t setBalanceRatioB(double dBlueBalanceRatio);
        int32_t getBalanceRatio( double &dRedBalanceRatio, double &dGreenBalanceRatio, double &dBlueBalanceRatio);
        int32_t getBalanceRatioMinMaxValue( double &dMinValue, double &dMaxValue);
        int32_t setAcquisitionFrameRate(double dFrameRate);  //设置图像采集的帧率
        int32_t getAcquisitionFrameRate( double &dFrameRate); //获取图像采集ed帧率
        int32_t userSetSave();  //保存用户设置，只能保存两个设置
        int32_t loadUserSet();  //加载用户设置，本函数中没有提供两个设置，但可以修改提供两个设置。
        int32_t setTriggerDelay( double dDelayTime);  //设置触发延时
        int32_t getTriggerDelay( double &dDelayTime);  //设置硬件触发模式：上升/下降
        int32_t setLineTriggerMode( bool bRisingEdge);
        int32_t getLineTriggerMode( bool &bRisingEdge);
        int32_t setLineDebouncerTimeAbs(double dLineDebouncerTimeAbs);  //设置IO滤波，输入为消抖值，注意不可设置比高电平的持续时间大，否则相机不出流
        int32_t getLineDebouncerTimeAbs( double &dLineDebouncerTimeAbs);
        int32_t setOutputTime( int nTimeMS); //设置输出时间
        int32_t setReverseX( bool flag);  //x轴反向
        int32_t setReverseY( bool flag);
        int32_t autoSetCameraIP();  //
        int32_t setCameraIp( char* ipAddress, char* subnetMask, char* gateway);
        int32_t setCameraPersistentIP();
        int32_t setBrightness(int _value);  //亮度
        int32_t setDigitalShift(int _value); //数字增益
        int32_t setBlackLevel(int _value);  //黑电平  20左右
        int32_t setSharpness(int _value);  //锐度
        int32_t getHeightRange(int64& min,int64& max,int64& inc);
        int32_t getWidthRange(int64& min,int64& max,int64& inc);
        int32_t getExposureRange(double& min,double& max);
        int32_t getGammaRange(double& min,double& max);
        int32_t getSharpnessRange(int64& min,int64& max,int64& inc);
        int32_t getBrightnessRange(int64& min,int64& max,int64& inc);
        int32_t getBlacklevelRange(int64& min,int64& max,int64& inc);
        int32_t getDigitalshiftRange(int64& min,int64& max,int64& inc);
        int32_t getGainrawRange(double& min,double& max);
        int32_t getBalanceRange(double& min,double& max);

        static std::vector<std::string> getDevices();
        void close();
        void init();
    private:
        bool inited=false;
        boost::shared_mutex image_mutex;
        std::shared_ptr<cv::Mat> mframe;
        CSystem &systemObj = CSystem::getInstance();
        ICameraPtr cameraSptr;
        IStreamSourcePtr streamPtr;
        std::string mSerialNumber;
        int width,height;
        double exposure;
        int blacklevel;
        int brightness,digitalshift;
        double gamma;
        int gainraw;
        int sharpness;
        std::vector<double> balance;
        int mcam_index=-1;
        int faildnum=0;
        void modifyCamralExposureTime(CSystem &systemObj);
        void LogPrinterFunc(const char* log);
        void displayDeviceInfo(TVector<ICameraPtr>& vCameraPtrList);
        char* trim(char* pStr);
        int isInputValid(char* pInpuStr);
        int selectDevice(int cameraCnt);
    };
}



#endif //DAHUA_MYDAHUACAM_H
